#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <functional>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
using namespace std;
using namespace LogModule;

const int defaultnum = -1;
using func_t = function<string(const string &)>;

class UdpServer
{
public:
    UdpServer(uint16_t port, func_t func)
        : _isrunning(false),
          _port(port),
          _func(func),
          _socket(defaultnum)
    {
    }

    void Init()
    {
        _socket = socket(AF_INET, SOCK_DGRAM, 0); // IPv4协议  UDP模式  默认值
        if (_socket < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            exit(1);
        }
        LOG(LogLevel::INFO) << "socket success" << _socket; //  标识符为3 012被占用

        struct sockaddr_in local;           //  IPv4 网络地址结构体
        bzero(&local, sizeof(local));       // 清空结构体
        local.sin_family = AF_INET;         // A=Address, F=Family, IN=Internet），表示使用 IPv4 协议；
        local.sin_port = htons(_port);      // hton 大端序 shost = 主机，network = 网络，short=16 位整数
        local.sin_addr.s_addr = INADDR_ANY; // 统定义的宏（值为 0x00000000，对应 IPv4 地址 0.0.0.0）

        //  这里为什么服务端要 bind ！！！！
        //  服务端需要稳定固定的地址，但客户端用临时地址即可
        int n = bind(_socket, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            exit(2);
        }
        LOG(LogLevel::INFO) << "bind success,socket:" << socket;
    }

    void Start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            char buffer[1024];       // 接收客户端数据
            struct sockaddr_in peer; // IPv4 数据接收结构体
            socklen_t len = sizeof(peer);
            //  接收完客户端信息，在进行发送
            ssize_t s = recvfrom(_socket, &buffer, sizeof(buffer) - 1, 0, (sockaddr *)&peer, &len);//接收客户端信息，buffer数组最后一位要0

            if (s > 0)
            {
                int peer_port = ntohs(peer.sin_port); // 
                string peer_ip = inet_ntoa(peer.sin_addr); //将 IP转换为string类格式
                buffer[s] = 0;
                string result = _func(buffer);  //将信息执行函数
                cout<<result<<endl;
                sendto(_socket,&buffer,result.size(),0,(sockaddr*)&peer,len);  //发送回给客户端
            }
        }
    }

    ~UdpServer()
    {
    }

private:
    bool _isrunning;
    int _socket;
    uint16_t _port;
    func_t _func;
};